package com.xmtlxx.common.utils.ftp;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.io.*;

/**
 * @author RonyChan
 * @since 2022/4/10 18:52
 */
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class FTPUtil {

//    private static String mode = "PASV";

    private static FTPClient getInstance(String host, String port, String userName, String password, String workingDirectory) {
        FTPClient ftpClient = new FTPClient();
        ftpClient.setControlEncoding("UTF-8");

        try {
            ftpClient.connect(host, Integer.valueOf(port));
            ftpClient.login(userName, password);

            int replyCode = ftpClient.getReplyCode();

            if (!FTPReply.isPositiveCompletion(replyCode)) {
                log.error("FTP服务（{}:{}）连接失败。", host, port);
                throw new Exception("FTP服务连接失败");
            }
            log.info("FTP服务（{}:{}）连接成功。", host, port);

//            if ("PORT".equals(mode)) {
//                ftpClient.enterLocalActiveMode();
//            } else {
//                ftpClient.enterLocalPassiveMode();
//            }

            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
            changeWorkingDirectory(ftpClient, workingDirectory);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return ftpClient;
    }

    /**
     * 连接
     *
     * @param hostname  ip或域名地址
     * @param port      端口
     * @param username  用户名
     * @param password  密码
     * @return 返回真则能连接
     */
    public static FTPClient connect(String hostname, int port, String username, String password) {
        FTPClient ftpClient = new FTPClient();
        try {
            //ftp初始化的一些参数
            ftpClient.connect(hostname, port);
            ftpClient.enterLocalPassiveMode();
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            ftpClient.setControlEncoding("UTF-8");
            if (ftpClient.login(username, password)) {
                log.info("连接ftp成功");
                return ftpClient;
            } else {
                log.error("连接ftp失败，可能用户名或密码错误");
                try {
                    close(ftpClient);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (IOException e) {
            log.error("连接失败，可能ip或端口错误");
            e.printStackTrace();
        }
        return null;
    }

    private static void changeWorkingDirectory(FTPClient ftpClient, String workingDirectory) throws IOException {
        String[] directories = workingDirectory.split("/");

        for (String directory : directories) {
            if (StringUtils.isBlank(directory)) {
                continue;
            }

            if (ftpClient.changeWorkingDirectory(directory)) {
                continue;
            }

            ftpClient.makeDirectory(directory);
            ftpClient.changeWorkingDirectory(directory);
        }
    }

    private static void close(FTPClient client) {
        if (null == client) {
            return;
        }

        try {
            client.logout();
        } catch (Exception e) {
            log.error("FTP退出登录失败。异常信息：{}", e.getMessage());
        } finally {
            if (client.isConnected()) {
                try {
                    client.disconnect();
                    log.info("FTP断开连接成功。");
                } catch (Exception e) {
                    log.error("FTP断开连接失败。异常信息：{}", e.getMessage());
                }
            }
        }
    }

    public static boolean upload(String filePath,String fileName, String host, String port, String userName, String password, String workingDirectory) {
        boolean flag = false;
        try{
            FileItem fileItem = createFileItem(new File(filePath+"/"+fileName));
            MultipartFile multipartFile = new CommonsMultipartFile(fileItem);
            InputStream inputStream = multipartFile.getInputStream();
            FTPClient client = getInstance(host, port, userName, password, workingDirectory);

            if (client.storeFile(fileName, inputStream)) {
                log.info("上传文件{}成功。", fileName);
                flag = true;
            } else {
                log.error("上传文件{}失败（{}）。", fileName, client.getReplyString());
            }

            close(client);
            inputStream.close();
        }catch (Exception e){
            log.error("上传文件{}失败（{}）。", fileName,e.getMessage());
        }
        return flag;
    }

    public static FileItem createFileItem(File file) {
        FileItemFactory factory = new DiskFileItemFactory(16, null);
        FileItem item = factory.createItem("textField", "text/plain", true, file.getName());
        int bytesRead = 0;
        byte[] buffer = new byte[8192];
        try {
            FileInputStream fis = new FileInputStream(file);
            OutputStream os = item.getOutputStream();
            while ((bytesRead = fis.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return item;
    }



    /**
     * 文件下载
     * @param fileName
     * @param localPath 不指定表示下载到当前项目下
     */
    public static void downloadFile(String localPath, String fileName, String host, String port, String userName, String password, String workingDirectory) {
        FTPClient ftpClient = getInstance(host, port, userName, password, workingDirectory);
        if (ftpClient == null) {
            return;
        }
        try {
            FTPFile[] ftpFiles = ftpClient.listFiles();
            for (FTPFile ftpFile : ftpFiles) {
                if (fileName.equals(ftpFile.getName())) {
                    File file = new File(localPath + fileName);
                    OutputStream outputStream = new FileOutputStream(file);
                    boolean result = ftpClient.retrieveFile(ftpFile.getName(), outputStream);
                    log.info("下载结果：" + result);
                    outputStream.close();
                }
            }
            ftpClient.logout();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
//        FTPClient client = connect("b2b2test.inditex.com",22,"UB2BTRFIDRECALLPRE","A*ncW7XIjb");
//        upload("/Users/rony/data/json/push", "getTagsRFID_1002_request.json","127.0.0.1","1988","ronychan","13599518139","/TO_ITX/TAGS_WITH_ORDER");
    }

}
